package cn.caskm.souvenirshopsystem.service.impl;

import cn.caskm.souvenirshopsystem.constants.BizConstants;
import cn.caskm.souvenirshopsystem.domain.Result;
import cn.caskm.souvenirshopsystem.domain.dto.PageDTO;
import cn.caskm.souvenirshopsystem.domain.po.Coupon;
import cn.caskm.souvenirshopsystem.domain.po.UserCoupon;
import cn.caskm.souvenirshopsystem.domain.query.UserCouponQuery;
import cn.caskm.souvenirshopsystem.domain.vo.UserCouponVO;
import cn.caskm.souvenirshopsystem.exceptions.BizException;
import cn.caskm.souvenirshopsystem.mapper.UserCouponMapper;
import cn.caskm.souvenirshopsystem.service.CouponService;
import cn.caskm.souvenirshopsystem.service.UserCouponService;
import cn.caskm.souvenirshopsystem.utils.UserContext;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserCouponServiceImpl extends ServiceImpl<UserCouponMapper, UserCoupon> implements UserCouponService {

    private final CouponService couponService;

    @Override
    public Result<PageDTO<UserCouponVO>> page(UserCouponQuery query) {
        // 获取参数
        Long pageNum = query.getPageNum();
        if (pageNum == null) {
            pageNum = BizConstants.DEFAULT_PAGE_NUM;
        }
        Long pageSize = query.getPageSize();
        if (pageSize == null) {
            pageSize = BizConstants.DEFAULT_PAGE_SIZE;
        }

        // 查询数据
        Page<UserCoupon> page = lambdaQuery()
                .eq(query.getUserId() != null, UserCoupon::getUserId, query.getUserId())
                .eq(query.getCouponId() != null, UserCoupon::getCouponId, query.getCouponId())
                .eq(StrUtil.isNotBlank(query.getStatus()), UserCoupon::getStatus, query.getStatus())
                .orderByDesc(UserCoupon::getReceiveTime)
                .page(new Page<>(pageNum, pageSize));

        List<UserCoupon> userCoupons = page.getRecords();
        if (CollUtil.isEmpty(userCoupons)) {
            return Result.success(PageDTO.empty());
        }

        // 获取优惠券信息
        Set<Integer> couponIds = userCoupons.stream().map(UserCoupon::getCouponId).collect(Collectors.toSet());
        Map<Integer, Coupon> couponMap = Collections.emptyMap();
        if (CollUtil.isNotEmpty(couponIds)) {
            List<Coupon> coupons = couponService.lambdaQuery()
                    .in(Coupon::getCouponId, couponIds)
                    .list();
            if (CollUtil.isNotEmpty(coupons)) {
                couponMap = coupons.stream().collect(Collectors.toMap(Coupon::getCouponId, c -> c));
            }
        }

        // 组装VO
        List<UserCouponVO> result = new ArrayList<>(userCoupons.size());
        for (UserCoupon userCoupon : userCoupons) {
            UserCouponVO vo = BeanUtil.copyProperties(userCoupon, UserCouponVO.class);
            Coupon coupon = couponMap.get(userCoupon.getCouponId());
            if (coupon != null) {
                vo.setCouponName(coupon.getCouponName());
                vo.setCouponType(coupon.getCouponType());
                vo.setDiscountAmount(coupon.getDiscountAmount());
                vo.setDiscountRate(coupon.getDiscountRate());
                vo.setMinAmount(coupon.getMinAmount());
                vo.setMaxDiscountAmount(coupon.getMaxDiscountAmount());
            }
            result.add(vo);
        }

        return Result.success(PageDTO.of(result, page.getPages(), page.getTotal()));
    }

    @Override
    @Transactional
    public Result<Void> receiveCoupon(Integer couponId) {
        Long userId = UserContext.getUser();
        if (userId == null) {
            throw new BizException("用户未登录");
        }

        // 获取优惠券信息
        Coupon coupon = couponService.getById(couponId);
        if (coupon == null) {
            throw new BizException("优惠券不存在");
        }

        // 检查优惠券状态
        if (!"1".equals(coupon.getStatus())) {
            throw new BizException("优惠券未发布或已结束");
        }

        // 检查时间
        LocalDateTime now = LocalDateTime.now();
        if (now.isBefore(coupon.getStartTime()) || now.isAfter(coupon.getEndTime())) {
            throw new BizException("优惠券不在有效期内");
        }

        // 检查剩余数量
        if (coupon.getRemainCount() <= 0) {
            throw new BizException("优惠券已被领完");
        }

        // 检查用户领取限制
        Long userReceivedCount = lambdaQuery()
                .eq(UserCoupon::getUserId, userId.intValue())
                .eq(UserCoupon::getCouponId, couponId)
                .count();
        if (userReceivedCount >= coupon.getLimitPerUser()) {
            throw new BizException("已达到个人领取上限");
        }

        // 创建用户优惠券记录
        UserCoupon userCoupon = new UserCoupon();
        userCoupon.setUserId(userId.intValue());
        userCoupon.setCouponId(couponId);
        userCoupon.setStatus("0"); // 未使用
        userCoupon.setReceiveTime(now);
        userCoupon.setExpireTime(coupon.getEndTime());
        save(userCoupon);

        // 更新优惠券剩余数量
        coupon.setRemainCount(coupon.getRemainCount() - 1);
        couponService.updateById(coupon);

        return Result.success();
    }

    @Override
    @Transactional
    public Result<Void> useCoupon(Long userCouponId, Integer orderId) {
        UserCoupon userCoupon = getById(userCouponId);
        if (userCoupon == null) {
            throw new BizException("用户优惠券不存在");
        }

        // 检查状态
        if (!"0".equals(userCoupon.getStatus())) {
            throw new BizException("优惠券不可用");
        }

        // 检查是否过期
        if (LocalDateTime.now().isAfter(userCoupon.getExpireTime())) {
            throw new BizException("优惠券已过期");
        }

        // 更新使用状态
        userCoupon.setStatus("1"); // 已使用
        userCoupon.setOrderId(orderId);
        userCoupon.setUseTime(LocalDateTime.now());
        updateById(userCoupon);

        // 更新优惠券使用数量
        Coupon coupon = couponService.getById(userCoupon.getCouponId());
        if (coupon != null) {
            coupon.setUsedCount(coupon.getUsedCount() + 1);
            couponService.updateById(coupon);
        }

        return Result.success();
    }

    @Override
    public Result<List<UserCouponVO>> getUserAvailableCoupons(Integer userId, BigDecimal orderAmount) {
        LocalDateTime now = LocalDateTime.now();
        List<UserCoupon> userCoupons = lambdaQuery()
                .eq(UserCoupon::getUserId, userId)
                .eq(UserCoupon::getStatus, "0") // 未使用
                .ge(UserCoupon::getExpireTime, now) // 未过期
                .orderByAsc(UserCoupon::getExpireTime)
                .list();

        if (CollUtil.isEmpty(userCoupons)) {
            return Result.success(new ArrayList<>());
        }

        // 获取优惠券信息并过滤满足条件的
        Set<Integer> couponIds = userCoupons.stream().map(UserCoupon::getCouponId).collect(Collectors.toSet());
        Map<Integer, Coupon> couponMap = Collections.emptyMap();
        if (CollUtil.isNotEmpty(couponIds)) {
            List<Coupon> coupons = couponService.lambdaQuery()
                    .in(Coupon::getCouponId, couponIds)
                    .list();
            if (CollUtil.isNotEmpty(coupons)) {
                couponMap = coupons.stream().collect(Collectors.toMap(Coupon::getCouponId, c -> c));
            }
        }

        // 组装VO并过滤
        List<UserCouponVO> result = new ArrayList<>();
        for (UserCoupon userCoupon : userCoupons) {
            Coupon coupon = couponMap.get(userCoupon.getCouponId());
            if (coupon != null && (coupon.getMinAmount() == null || orderAmount.compareTo(coupon.getMinAmount()) >= 0)) {
                UserCouponVO vo = BeanUtil.copyProperties(userCoupon, UserCouponVO.class);
                vo.setCouponName(coupon.getCouponName());
                vo.setCouponType(coupon.getCouponType());
                vo.setDiscountAmount(coupon.getDiscountAmount());
                vo.setDiscountRate(coupon.getDiscountRate());
                vo.setMinAmount(coupon.getMinAmount());
                vo.setMaxDiscountAmount(coupon.getMaxDiscountAmount());
                result.add(vo);
            }
        }

        return Result.success(result);
    }

    @Override
    public Result<Boolean> checkCouponAvailable(Long userCouponId, BigDecimal orderAmount) {
        UserCoupon userCoupon = getById(userCouponId);
        if (userCoupon == null) {
            return Result.success(false);
        }

        // 检查状态
        if (!"0".equals(userCoupon.getStatus())) {
            return Result.success(false);
        }

        // 检查是否过期
        if (LocalDateTime.now().isAfter(userCoupon.getExpireTime())) {
            return Result.success(false);
        }

        // 检查最低消费金额
        Coupon coupon = couponService.getById(userCoupon.getCouponId());
        if (coupon != null && coupon.getMinAmount() != null) {
            if (orderAmount.compareTo(coupon.getMinAmount()) < 0) {
                return Result.success(false);
            }
        }

        return Result.success(true);
    }
}
